package rlm.rlcontainer;

import java.util.ArrayList;
import java.util.List;

import rlm.constraints.Directions;
import alm.LayoutSpec;

public class CompoundPlaceHolder extends PlaceHolder {


	private static int serial = 1;

	List<PlaceHolder> children;

	/**
	 * Primary constructor
	 * 
	 * @param name
	 */
	public CompoundPlaceHolder(String name) {
		super(name);
		children = new ArrayList<PlaceHolder>();
	}

	public CompoundPlaceHolder() {
		this("CPlace" + serial++);
	}

	// cdildren functions
	public List<PlaceHolder> getChildren() {
		return children;
	}

	public PlaceHolder getChild(int i) {
		if (children.size() > i)
			return children.get(i);
		else
			return null;
	}

	@Override
	public void createArea(LayoutSpec ls) {
		for (PlaceHolder child : children){
			child.createArea(ls);
		}
	}

	/**
	 * Adds this child, fails if this child is the ancestor of this place
	 * 
	 * 1. if @param is ancestor, it wont be added 2. if @param if some, but not
	 * direct child, it will be removed from it's parent 2. if @param's children
	 * are contained, they will be removed
	 * 
	 * @param a
	 */
	public void addChild(PlaceHolder a) {
		if (a.contains(this))
			return; // this is an exception...

		if (children.contains(a)) {
			// direct child - nothing to do
		} else if (this.contains(a)) {
			remove(a);
		}
		
		// remove all children of a from this

		if (a instanceof CompoundPlaceHolder) 
			for (PlaceHolder child : ((CompoundPlaceHolder)a).getChildren())
				remove(child);
			
		if (!children.contains(a))
			children.add(a);
	}

	/**
	 * recursive contains
	 */
	public boolean contains(PlaceHolder a) {
		if (super.contains(a))
			return true;

		if (this.children.contains(a))
			return true;

		boolean ans = false;
		for (PlaceHolder child : children) {
			ans |= child.contains(a);
		}

		return ans;
	}

	/**
	 * recursive remove
	 * 
	 * @param p
	 */
	public void remove(PlaceHolder p) {
		if (children.remove(p))
			return;

		// not direct child
		for (PlaceHolder child : children) {
			if (child instanceof CompoundPlaceHolder) {
				((CompoundPlaceHolder) child).remove(p);
			}
		}
	}

	@Override
	public boolean isSimple() {
		return false;
	}
	
	
	public void calculateOuterBox() {
		for(PlaceHolder p : children){
			for(Directions dir : Directions.values())
				if (p.getOuterBounds().getTab(dir) == null && p.getPlaces(dir).size() == 0)
					p.getOuterBounds().setTab(dir, this.getOuterBounds().getTab(dir));
			
			if (p instanceof CompoundPlaceHolder){
				((CompoundPlaceHolder)p).calculateOuterBox();
			}
		}
	}
	
}
